
#include <memory.h>

#include "land_base.h"
#include "land_graphics.h"
#include "land_math.h"

#define LAND_2D_CORE

#include "init.h"

static struct{
	LandShader* shader;
	unsigned mpos;
	LandDraw draw;
}ctx = { 0 };

static void
makeText(LandScene* scene, LandText* text){
	landClearVertex(text->vertex);
	unsigned step = 0;
	unsigned pos = 0;
	uint32_t ch;
	LandGlyph glyph;
	LandVector* color = &text->obj.color;
	unsigned count = 0;
	LandFloat fw, fh;
	LandVector uv = { 0.f, 0.f, 1.f, 1.f };
	unsigned offset = 0;
	LandMatrix2D transform;
	LandFloat xpos = 0;
	LandFloat ypos = 0;
	while (ch = landUtf8(text->str + pos, &step)) {
		pos += step;
		landRegFont(text->font, ch, 12, &glyph);
		fw = (LandFloat)glyph.fw;
		fh = (LandFloat)glyph.fh;
		landIdentityMatrix2D(&transform);
		LandVector2D move = {
			xpos + glyph.x,
			(LandFloat)glyph.y,
			1.f
		};
		landMoveMatrix2D(&transform, &move);
		xpos += fw;
		LandVector rect = { 0.f, 0.f, (LandFloat)glyph.width, (LandFloat)glyph.height };
		count += landPushObjRect(
			text->vertex, &rect, &glyph.uv, color, &offset, &transform);
	}

	landUploadVertex(text->vertex);
	LandDraw* draw = &ctx.draw;
	draw->offset = 0;
	draw->count = count;
	draw->vertex = text->vertex;
	draw->shader = ctx.shader;
	scene->draw = draw;
}

static void
drawText(LandScene* scene, LandObj* obj) {
	LandText* text = (LandText*)obj;
	makeText(scene, text);
}

static void
freeText(LandRef* ref) {
	LandText* text = (LandText*)ref;
	landReleaseRef(text->vertex);
	if (text->str) {
		free(text->str);
	}
}

LAND_2D_API LandText*
landNewText(LandFont* font) {
	LandText* text = landNewExtendObj(sizeof(LandText), freeText);
	text->font = font;
	text->vertex = landNewVertex(16);
	text->obj.draw = drawText;
	return text;
}


LAND_2D_API void
landTextStr(LandText* text, const char* str, size_t len) {
	if (text->str) {
		if (text->len != len) {
			free(text->str);
			text->str = NULL;
		}
	}
	text->len = len;
	if (len) {
		text->str = malloc(len + 1);
		memcpy(text->str, str, len);
		text->str[len] = 0;
	}
	text->strDirty = 1;
}


void
landInitTextContext() {
	ctx.shader = landNewStdShader(LAND_STD_SHADER_COLOR_TEXTURE);
	landRetainRef(ctx.shader);
}